package lee.vioson.ebook.viewmodels

import android.os.CountDownTimer
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.stateIn
import lee.vioson.composecommon.base.mvi.BaseViewModel
import lee.vioson.composecommon.base.mvi.Reducer
import lee.vioson.composecommon.base.mvi.UiEvent
import lee.vioson.composecommon.base.mvi.UiState
import lee.vioson.ebook.data.AppContainer
import lee.vioson.remotedata.manager.AppConfigManager

class LauncherViewModel(appContainer: AppContainer) :
    AppViewModel<LauncherViewModel.State, LauncherViewModel.Event>(appContainer.appEvent) {
    companion object {
        fun factory(appContainer: AppContainer) =
            viewModelFactory {
                initializer {
                    LauncherViewModel(appContainer)
                }
            }
    }

    private val reducer = SubReducer(State())

    override val state: StateFlow<State>
        get() = reducer.state

    override fun sendEvent(event: Event) {
        reducer.sendEvent(event)
    }

    /**
     * local cache data
     */
    val cacheData = AppConfigManager.INTANCE.getInitAppConfig(appContainer.context)
        .catch { handleException(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)

    /**
     * real time data
     */
    val initData =
        appContainer.initRepository.initData(appContainer.uniqueId)
            .catch { handleException(it) }
            .onCompletion { anonymousLogin.launchIn(viewModelScope) }
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)

    /**
     * anonymousLogin
     */
    private val anonymousLogin = appContainer.loginRepository.anonymousLogin(
        appContainer.uniqueId,
        appContainer.customerSource
    )
        .catch { handleException(it) }
        .onCompletion { startCountdown() }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)

    private val totalWaitTime = 2 * 1000L
    private var countDownTimer: CountDownTimer? = null

    private fun startCountdown() {
        sendEvent(Event.OnCountDown((totalWaitTime / 1000).toInt()))
        countDownTimer = object : CountDownTimer(totalWaitTime, 1000L) {
            override fun onTick(millisUntilFinished: Long) {
                sendEvent(Event.OnCountDown(((totalWaitTime - millisUntilFinished) / 1000).toInt()))
            }

            override fun onFinish() {
                sendEvent(Event.OnCountDown(-1))
                sendEvent(Event.OnLauncherEnd)
                countDownTimer = null
            }

        }
        countDownTimer!!.start()
    }


    private class SubReducer(initialState: State) :
        Reducer<State, Event>(initialState) {
        override fun reduce(oldState: State, event: Event) {
            when (event) {
                is Event.OnLauncherEnd -> {
                    setState(oldState.copy(showLauncher = false))
                }

                is Event.OnCountDown -> setState(oldState.copy(countDown = event.countDown))
            }
        }
    }
    sealed class Event : UiEvent {
        object OnLauncherEnd : Event()

        data class OnCountDown(val countDown: Int) : Event()
    }

    data class State(
        val showLauncher: Boolean = true,
        val countDown: Int = -1
    ) : UiState

}
